#include "jsapi.h"
#include "js-engine.h"
#include "desktopClasses.h"
#include "basicElementClass.h"
#include "mainview-parser.h"

static JSBool img_new(JSContext *cx, JSObject *obj, uintN argc, jsval *args, jsval *rval);
static JSBool img_setSrcSize(JSContext *cx, JSObject *obj, uintN argc, jsval *args, jsval *rval);
static JSBool img_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);

extern JSBool basicElement_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);

gboolean draw_image(GtkWidget *event_box, GdkEventExpose *event, gpointer ptr);

static JSFunctionSpec img_methods[] = {
    {"setSrcSize", img_setSrcSize, 2, 0, 0}, 
    {NULL, NULL, 0, 0, 0}
};

JSClass imgClass =
    { "img", JSCLASS_HAS_PRIVATE,
      JS_PropertyStub, JS_PropertyStub,JS_PropertyStub, img_SetProperty,
      JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
      JSCLASS_NO_OPTIONAL_MEMBERS
    };

struct property_parser img_parser[] = {
    /* from basicElement */
    {"cursor", set_property_string_value},
    {"dropTarget", set_property_boolean_value},
    {"enabled", set_property_boolean_value},
    {"height", set_property_integer_value},
    {"hitTest", set_property_string_value},
    {"mask", set_property_string_value},
    {"name", set_property_string_value},
    {"offsetHeight", set_property_integer_value},
    {"offsetWidth", set_property_integer_value},
    {"offsetX", set_property_integer_value},
    {"offsetY", set_property_integer_value},
    {"opacity", set_property_integer_value},
    {"pinX", set_property_integer_value},
    {"pinY", set_property_integer_value},
    {"rotation", set_property_float_value},
    {"tagName", set_property_string_value},
    {"tooltip", set_property_string_value},
    {"width", set_property_integer_value},
    {"visible", set_property_boolean_value},
    {"x", set_property_integer_value},
    {"y", set_property_integer_value},
		
    {"src", set_property_string_value},
    {"srcHeight", set_property_integer_value},
    {"srcWidth", set_property_integer_value},
		
    {ONCLICK, set_property_function_value},
    {ONRCLICK, set_property_function_value},
    {ONDBLCLICK, set_property_function_value},
    {ONRDBLCLICK, set_property_function_value},
    {"ondragdrop", set_property_function_value},
    {"ondragover", set_property_function_value},
    {ONFOCUSIN, set_property_function_value},
    {ONFOCUSOUT, set_property_function_value},
    {ONKEYDOWN, set_property_function_value},
    {ONKEYPRESS, set_property_function_value},
    {ONKEYUP, set_property_function_value},
    {ONMOUSEDOWN, set_property_function_value},
    {ONMOUSEMOVE, set_property_function_value},
    {ONMOUSEOUT, set_property_function_value},
    {ONMOUSEOVER, set_property_function_value},
    {ONMOUSEUP, set_property_function_value},
    {ONMOUSEWHEEL, set_property_function_value},
    {NULL, NULL},
};

static JSBool img_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    desktop_element *element = JS_GetPrivate(cx, obj);
    if(!element->view)
	return JS_TRUE;

    basicElement_SetProperty(cx, obj, id, vp);
    gtk_widget_queue_draw(element->view);

    return JS_TRUE;	
}

static JSBool img_setSrcSize(JSContext *cx, JSObject *obj, uintN argc, jsval *args, jsval *rval)
{
    gint width, height;
    g_return_val_if_fail(argc == 2, JS_FALSE);
    g_return_val_if_fail(JSVAL_IS_INT(args[0]), JS_FALSE);
    g_return_val_if_fail(JSVAL_IS_INT(args[1]), JS_FALSE);
    width = JSVAL_TO_INT(args[0]);
    height = JSVAL_TO_INT(args[1]);
    return JS_TRUE;
}

static JSBool img_new(JSContext *cx, JSObject *obj, uintN argc, jsval *args, jsval *rval)
{
    return JS_TRUE;
}

JSObject *imgClass_init(js_engine *engine, JSObject *parent)
{
    JSObject *proto = NULL;
    proto = JS_InitClass(engine->cx, engine->glob, parent,
			 &imgClass, img_new,
			 0,NULL,NULL,NULL,NULL);
    g_return_val_if_fail(proto, FALSE);
    g_return_val_if_fail(JS_DefineFunctions(engine->cx, proto, img_methods), FALSE);
    return proto;
}

gboolean draw_image(GtkWidget *widget, GdkEventExpose *event, gpointer ptr) {
    jsval x, y, src, srcWidth, srcHeight, opacity, visible, width, height;
    desktop_element *element = (desktop_element *)ptr;

    cairo_t *cr= NULL;
    gdouble x_pos = 0, y_pos = 0, opacity_ratio = 1;
    gint width_val = -1, height_val = -1;
    guint imgWidth = 0, imgHeight = 0;
    gchar *src_path = NULL;
    GError *err = NULL;
    GdkPixbuf *image_buf = NULL;

    JS_GetProperty(element->engine->cx, element->jsobj, "x", &x);
    JS_GetProperty(element->engine->cx, element->jsobj, "y", &y);
    JS_GetProperty(element->engine->cx, element->jsobj, "src", &src);
    JS_GetProperty(element->engine->cx, element->jsobj, "srcHeight", &srcHeight);
    JS_GetProperty(element->engine->cx, element->jsobj, "srcWidth", &srcWidth);
    JS_GetProperty(element->engine->cx, element->jsobj, "opacity", &opacity);
    JS_GetProperty(element->engine->cx, element->jsobj, "visible", &visible);
    JS_GetProperty(element->engine->cx, element->jsobj, "width", &width);
    JS_GetProperty(element->engine->cx, element->jsobj, "height", &height);

    src_path = trans_unix_path_new(JS_GetStringBytes(JS_ValueToString(element->engine->cx, src)));
    image_buf = gdk_pixbuf_new_from_file(src_path, &err);
    g_free(src_path);
    if(err){
        g_error_free(err);
    	return FALSE;
    }
    imgWidth = gdk_pixbuf_get_width(image_buf);
    imgHeight = gdk_pixbuf_get_height(image_buf);

    if (JSVAL_IS_NUMBER(x))
        JS_ValueToNumber(element->engine->cx, x, &x_pos);
    if (JSVAL_IS_NUMBER(y))
        JS_ValueToNumber(element->engine->cx, y, &y_pos);
    if (JSVAL_IS_INT(opacity)) {
        int value= JSVAL_TO_INT(opacity);
        opacity_ratio = (gdouble)value/255;
    }
    if (JSVAL_IS_BOOLEAN(visible)) {
        if (!JSVAL_TO_BOOLEAN(visible))
            opacity_ratio = 0;
    }

    cr = gdk_cairo_create(widget->window);
    if (JSVAL_IS_INT(width)) {
        width_val= JSVAL_TO_INT(width);
        cairo_scale(cr, (gdouble)width_val/imgWidth, 1);
        x_pos = (gdouble)imgWidth/width_val*x_pos;
    }

    if (JSVAL_IS_INT(height)) {
        height_val= JSVAL_TO_INT(height);
        cairo_scale(cr, 1, (gdouble)height_val/imgHeight);
        y_pos = (gdouble)imgHeight/height_val*y_pos;
    }
    gdk_cairo_set_source_pixbuf(cr, image_buf, x_pos, y_pos);
    cairo_paint_with_alpha(cr, opacity_ratio);
    gtk_widget_set_size_request(element->view, imgWidth, imgHeight);
    cairo_destroy(cr);
    return FALSE;
}

void desktop_element_set_view_img(js_engine *engine, desktop_element *element) {
    element->view = gtk_event_box_new();
    gtk_event_box_set_visible_window(GTK_EVENT_BOX(element->view), FALSE);
    gtk_widget_add_events(element->view,GDK_ALL_EVENTS_MASK);
    g_signal_connect(element->view, "expose-event", 
		     G_CALLBACK(draw_image), element);

    set_element_event_cb(element);
}
